package indi.zqc.mqtt.customer.configuration;


import com.alibaba.fastjson.JSON;
import indi.zqc.mqtt.customer.handler.MqttMessageGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;

@Configuration
public class AppConfiguration {

    @Value("${mqtt.broker.serverUri}")
    private String serviceUri;

    @Value("${mqtt.broker.username:}")
    private String username;

    @Value("${mqtt.broker.password:}")
    private String password;

    @Value("${mqtt.topic}")
    private String topic;

    @Value("${mqtt.clientId}")
    private String clientId;

    @Value("${mqtt.qos}")
    private Integer qos;

    @Value("${mqtt.completionTimeout}")
    private Integer completionTimeout;

    /**
     * 消息通道
     * @return
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    /**
     * mqtt服务器配置
     * @return
     */
    @Bean
    public MqttPahoClientFactory clientFactory() {
        DefaultMqttPahoClientFactory clientFactory = new DefaultMqttPahoClientFactory();
        clientFactory.setServerURIs(serviceUri);
        clientFactory.setUserName(username);
        clientFactory.setPassword(password);

        return clientFactory;
    }

    /**
     * 通道适配器
     * @param clientFactory
     * @param mqttInputChannel
     * @return
     */
    @Bean
    public MessageProducer inbound(MqttPahoClientFactory clientFactory, MessageChannel mqttInputChannel) {
        //clientId 客户端ID，生产端和消费端的客户端ID需不同，不然服务器会认为是同一个客户端，会接收不到信息
        //topic 订阅的主题
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId+2, clientFactory, topic);
        //超时时间
        adapter.setCompletionTimeout(completionTimeout);
        //转换器
        DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
        converter.setPayloadAsBytes(true);
        adapter.setConverter(converter);
        adapter.setQos(qos);
        adapter.setOutputChannel(mqttInputChannel);
        return adapter;
    }

    /**
     * 通道适配器
     * @param clientFactory
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MqttPahoMessageHandler mqttOutbound(MqttPahoClientFactory clientFactory) {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, clientFactory);
        messageHandler.setAsync(true);
        messageHandler.setDefaultQos(1);
        messageHandler.setDefaultRetained(false);
        messageHandler.setAsyncEvents(false);
        return messageHandler;
    }


    private int[] dataPos = new int[8];
    public AppConfiguration() {
        //按顺序定义数据位移
        int n = 0;
        //包头
        dataPos[n] = 0;

        n++;
        //数据类型
        dataPos[n] = dataPos[n-1] + 2;

        //中继器序列号
        n++;
        dataPos[n] = dataPos[n-1] + 1;

        //唯一标识
        n++;
        dataPos[n] = dataPos[n-1] + 14;

        //包号
        n++;
        dataPos[n] = dataPos[n-1] + 4;

        //时间戳
        n++;
        dataPos[n] = dataPos[n-1] + 4;

        //数据长度
        n++;
        dataPos[n] = dataPos[n-1] + 13;

        //心电数据
        n++;
        dataPos[n] = dataPos[n-1] + 2;
    }
    /**
     * 心电数据解析
     * @param payload
     */
    public byte[] dataVerification(Object payload) {
        /**
         *
         数据类型	0x01	1字节，0x01: ECG
         包头	0x5A 0x6B	2字节
         心贴序列号		14字节
         包号		4字节（小端）
         时间戳         13字节（字符串）
         数据长度	0x00 + 0x7f  一个byte 一个字节	2字节（小端）
         心电数据		≤990字节(15的倍数)
         包尾	0x7c 0x8d 	2字节
         */
//        DataProto.Content.Builder proto =  DataProto.Content.newBuilder();
        byte [] data =(byte[]) payload;
        int n = 0;
        int len = 0; //数据长度
        /** 校验包头 类型 */
        len = 3;
        byte[] byteHeader = new byte[len];
        System.arraycopy(data, dataPos[n], byteHeader, 0, len);
        /** 包尾 */
        len = 2;
        byte[] byteTail = new byte[len];
        System.arraycopy(data, data.length-2, byteTail, 0, len);
        if (Arrays.equals(byteHeader, new byte[]{0x5A, 0x6B, 0x01})&& Arrays.equals(byteTail, new byte[]{0x7c, (byte) 0x8d})){
            //TODO
            /** 数据类型 */
            n++;
            len = dataPos[n] - dataPos[n-1];
            byte[] ecgType = new byte[len];
            System.arraycopy(data, dataPos[n], ecgType, 0, len);
            /** 获取 心贴序列号  */
            n++;
            len = dataPos[n] - dataPos[n-1];
            byte[] sequence = new byte[14];
            System.arraycopy(data, dataPos[n], sequence, 0, 14);
            try {
                String serial  = new String (sequence,"utf-8");
//                String seq = new BigInteger(1, sequence).toString(16);
                System.out.println("序列号"+serial);
                /** 唯一标识 */
                n++;
                len = dataPos[n] - dataPos[n-1];
                byte[] id = new byte[len];
                System.arraycopy(data, dataPos[n], id, 0,len);
                Integer dataId = littleEndian2Int(id);
                /** 包号*/
                n++;
                len = dataPos[n] - dataPos[n-1];
                byte[] packback = new byte[len];
                System.arraycopy(data, dataPos[n], packback, 0,len);
                Integer sqe = littleEndian2Int(packback);
                System.out.println("包号"+sqe);
//                proto.setType("ECG");
                /** 时间戳 */
                n++;
                len = dataPos[n] - dataPos[n-1];
                byte[] time = new byte[len];
                System.arraycopy(data, dataPos[n], time, 0,len);
                String timeer =  new String (time,"utf-8");

            } catch (Exception e) {
                e.printStackTrace();
            }
            /** 长度 */
            n++;
            len = dataPos[n] - dataPos[n-1];
            byte[] length = new byte[len];
            System.arraycopy(data, dataPos[n], length, 0,len);
            len = littleEndian2Int(length);
//            len = littleEndian2Int(length);
        }
        return null;
    }
    /**
     * 转换byte数组为Char（小端）
     * @return
     * @note 数组长度至少为2，按小端方式转换
     */
    public static int littleEndian2Int(byte[] len) {
        if (len.length ==4){
            return ByteBuffer.wrap(len).order(ByteOrder.LITTLE_ENDIAN).getInt();
        }else {
            if(len.length < 2)
                return (char)-1;
            int iRst = (len[0] & 0xFF);
            iRst |= (len[1] & 0xFF) << 8;
            return (char)iRst;
        }
    }

    public static void main(String[] args) {
        System.out.println(6 << 8);
        System.out.println(32 >> 4);
        System.out.println(32 | 2);
        Map<String,String> hashMap = new HashMap<>();
       String a=  hashMap.get("1");
        System.out.println(a);
       System.out.println(2356 & 0xFF);
    }
}
